﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ifunction
{
    /// <summary>
    /// Class Extension.
    /// </summary>
    public static class Extension
    {
        /// <summary>
        /// Gets the string value.
        /// </summary>
        /// <param name="anyObject">Any object.</param>
        /// <param name="defaultString">The default string.</param>
        /// <returns>System.String.</returns>
        public static string GetStringValue(this object anyObject, string defaultString = "")
        {
            return anyObject != null ? anyObject.ToString() : defaultString;
        }

        /// <summary>
        /// Gets the string value.
        /// </summary>
        /// <param name="anyObject">Any object.</param>
        /// <param name="defaultString">The default string.</param>
        /// <returns>System.String.</returns>
        public static string GetStringValue(this string anyObject, string defaultString = "")
        {
            return !string.IsNullOrWhiteSpace(anyObject) ? anyObject : defaultString;
        }

        /// <summary>
        /// Sets the cookie by string.
        /// </summary>
        /// <param name="cookieCollection">The cookie collection.</param>
        /// <param name="cookieString">The cookie string.</param>
        /// <param name="hostDomain">The host domain.</param>
        public static void SetCookieByString(this CookieCollection cookieCollection, string cookieString, string hostDomain)
        {
            if (cookieCollection != null && !string.IsNullOrWhiteSpace(cookieString))
            {
                string[] cookieProperties = cookieString.Split(new char[] { ' ', ';' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var property in cookieProperties)
                {
                    string[] keyValue = property.Split(new char[] { '=' }, 2);
                    if (keyValue.Length >= 2)
                    {
                        string key = keyValue[0];
                        string value = keyValue[1];
                        Cookie cookie = new Cookie(key, value, null, hostDomain);

                        cookieCollection.Add(cookie);
                    }
                }
            }
        }

        /// <summary>
        /// Sets the cookie by string.
        /// </summary>
        /// <param name="cookieContainer">The cookie container.</param>
        /// <param name="cookieString">The cookie string.</param>
        /// <param name="hostDomain">The host domain.</param>
        public static void SetCookieByString(this CookieContainer cookieContainer, string cookieString, Uri hostDomain)
        {
            if (hostDomain != null && cookieContainer != null && !string.IsNullOrWhiteSpace(cookieString))
            {
                var cookieCollection = cookieContainer.GetCookies(hostDomain);

                if (cookieCollection == null)
                {
                    cookieCollection = new CookieCollection();
                    cookieCollection.SetCookieByString(cookieString, hostDomain.Host);
                    cookieContainer.Add(cookieCollection);
                }
            }
        }

        /// <summary>
        /// Automatics the cookie raw string.
        /// </summary>
        /// <param name="cookieCollection">The cookie collection.</param>
        /// <returns>System.String.</returns>
        public static string ToCookieRawString(this CookieCollection cookieCollection)
        {
            StringBuilder builder = new StringBuilder();

            if (cookieCollection != null)
            {
                foreach (Cookie cookie in cookieCollection)
                {
                    builder.AppendFormat("{0}={1}; ", cookie.Name, cookie.Value);
                }
            }

            return builder.ToString();
        }

        /// <summary>
        /// Creates the XML node.
        /// </summary>
        /// <param name="anyObject">Any object.</param>
        /// <param name="nodeName">Name of the node.</param>
        /// <returns>XElement.</returns>
        public static XElement CreateXmlNode(this object anyObject, string nodeName = null)
        {
            return XElement.Parse(string.Format("<{0}></{0}>", !string.IsNullOrWhiteSpace(nodeName) ? nodeName : "Item"));
        }

        /// <summary>
        /// Gets the attribute value.
        /// </summary>
        /// <param name="xElement">The x element.</param>
        /// <param name="attribute">The attribute.</param>
        /// <returns>System.String.</returns>
        public static string GetAttributeValue(this XElement xElement, string attribute)
        {
            string result = string.Empty;

            if (xElement != null && !string.IsNullOrWhiteSpace(attribute))
            {
                var attr = xElement.Attribute(attribute);
                if (attr != null)
                {
                    result = attr.Value;
                }
            }

            return result;
        }

        /// <summary>
        /// To the long.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns>System.Int64.</returns>
        public static long ToLong(this object data, long defaultValue = 0)
        {
            long result;
            if (data == null || data == DBNull.Value || !long.TryParse(data.ToString(), out result))
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// Automatics the int.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns>System.Int32.</returns>
        public static int ToInt(this object data, int defaultValue = 0)
        {
            int result;
            if (data == null || data == DBNull.Value || !int.TryParse(data.ToString(), out result))
            {
                result = defaultValue;
            }

            return result;
        }

        /// <summary>
        /// To GUID.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns>System.Nullable{Guid}.</returns>
        public static Guid? ToGuid(this object data, Guid? defaultValue = null)
        {
            Guid result;
            return (data == null || data == DBNull.Value || !Guid.TryParse(data.ToString(), out result)) ? defaultValue : result;
        }

        /// <summary>
        /// Automatics the UTC.
        /// </summary>
        /// <param name="dateTimeObject">The date time object.</param>
        /// <param name="currentTimeZoneOffset">The current time zone offset.</param>
        /// <returns>DateTime.</returns>
        public static DateTime ToUtc(this DateTime dateTimeObject, TimeSpan currentTimeZoneOffset)
        {
            if (dateTimeObject.Kind == DateTimeKind.Unspecified)
            {
                dateTimeObject = (new DateTime(dateTimeObject.Year, dateTimeObject.Month, dateTimeObject.Day, dateTimeObject.Hour, dateTimeObject.Minute, dateTimeObject.Second, dateTimeObject.Millisecond, DateTimeKind.Utc)) - currentTimeZoneOffset;
            }

            if (dateTimeObject.Kind == DateTimeKind.Local)
            {
                dateTimeObject = dateTimeObject.ToUniversalTime();
            }

            return dateTimeObject;
        }

        /// <summary>
        /// Automatics the UTC.
        /// </summary>
        /// <param name="dateTimeObject">The date time object.</param>
        /// <returns>DateTime.</returns>
        public static DateTime ToUtc(this DateTime dateTimeObject)
        {
            return ToUtc(dateTimeObject, TimeZone.CurrentTimeZone.GetUtcOffset(dateTimeObject));
        }
    }
}
